package com.hjb.service.impl.recharge;

import com.hjb.service.config.constant.Constants;
import com.hjb.service.config.properties.FuiouProperties;
import com.hjb.service.domain.product.SiteUserBuy;
import com.hjb.service.domain.product.SiteUserBuyExample;
import com.hjb.service.domain.recharge.SiteUserRecharge;
import com.hjb.service.domain.recharge.SiteUserRechargeExample1;
import com.hjb.service.domain.siteuser.SiteUser;
import com.hjb.service.domain.siteuser.SiteUserExample;
import com.hjb.service.domain.siteuseraccount.SiteUserAccount;
import com.hjb.service.domain.siteuseraccount.SiteUserAccountExample;
import com.hjb.service.gateway.fuiou.DESCoderFUIOU;
import com.hjb.service.gateway.fuiou.FyPayConstant;
import com.hjb.service.gateway.fuiou.FyPayInfo;
import com.hjb.service.gateway.fuiou.FyPayReturnInfo;
import com.hjb.service.gateway.fuiou.FyPayUtils;
import com.hjb.service.gateway.fuiou.HttpPoster;
import com.hjb.service.gateway.fuiou.MD5;
import com.hjb.service.mapper.SiteUserAccountMapper;
import com.hjb.service.mapper.SiteUserBuyMapper;
import com.hjb.service.mapper.SiteUserMapper;
import com.hjb.service.mapper.SiteUserRechargeMapper;
import com.hjb.service.product.SiteUserBuyService;
import com.hjb.service.recharge.FYRechargeService;
import com.hjb.service.user.SiteSysAccountService;
import com.hjb.service.utils.MapUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by gy on 2017/7/28.
 * 充值接口实现
 */
@Service
public class FYRechargeServiceImpl implements FYRechargeService {

	private Logger log = LoggerFactory.getLogger(getClass());

	@Autowired
	private SiteUserMapper siteUserMapper;
	@Autowired
	private SiteUserRechargeMapper siteUserRechargeMapper;
	@Autowired
	private SiteUserAccountMapper siteUserAccountMapper;
	@Autowired
	private FuiouProperties fuiouProperties;
	@Autowired
	private SiteUserBuyMapper siteUserBuyMapper;
	@Autowired
	private SiteUserBuyService siteUserBuyService;
	@Autowired
	private SiteSysAccountService siteSysAccountService;

	@Override
	public Map<String, Object> recharge(SiteUserBuy siteUserBuy) {
		Map<String, Object> resMap = new HashMap<String, Object>();
		try {
			//查询用户信息
			SiteUser siteUser = new SiteUser();
			SiteUserExample siteUserExample = new SiteUserExample();
			siteUserExample.createCriteria().andUserIdEqualTo(siteUserBuy.getUserId());
			List<SiteUser> siteUserList = siteUserMapper.selectByExample(siteUserExample);
			if (siteUserList == null || siteUserList.size() == 0) {
				resMap.put("result_code", MapUtil.INTF_ERR_CODE);
				resMap.put("result_info", "无用户信息");
				return resMap;
			}
			siteUser = siteUserList.get(0);
			FyPayInfo fyPayInfo = new FyPayInfo();
			// 构造支付请求对象
			fyPayInfo.setMchnt_cd(FyPayUtils.nvl(fuiouProperties.getMerchId()));
			fyPayInfo.setOrder_id(FyPayUtils.nvl(siteUserBuy.getOrderNo()));
			// 富友传参数金额以分为单位
			BigDecimal amout = siteUserBuy.getAmount().multiply(new BigDecimal(100));
			fyPayInfo.setOrder_amt(amout.setScale(0));
			fyPayInfo.setUser_type(FyPayConstant.FyPayType.manage.getV());
			fyPayInfo.setCert_type(FyPayConstant.CertType.IDCARD);
			fyPayInfo.setUser_id((long) siteUserBuy.getUserId());
			fyPayInfo.setBack_notify_url(FyPayUtils.nvl(fuiouProperties.getReturnUrl()));
			// 支付info
			fyPayInfo.setCard_no(FyPayUtils.nvl(siteUser.getBankCardNo()));
			fyPayInfo.setCert_no(FyPayUtils.nvl(siteUser.getCardNumber()));
			fyPayInfo.setCardholder_name(FyPayUtils.nvl(siteUser.getName()));
			switch (siteUserBuy.getTerminalType()){
				case 4://h5
					fyPayInfo.setPage_notify_url(fuiouProperties.getNotifyUrlh5());
					fyPayInfo.setPage_notify_url_err(fuiouProperties.getNotifyErrUrlh5());
					break;
				case 2://ios
				case 3://android
					fyPayInfo.setPage_notify_url(fuiouProperties.getNotifyUrl());
					fyPayInfo.setPage_notify_url_err(fuiouProperties.getNotifyErrUrl());
					break;
			}

			// RSA加签字符串
			StringBuffer sb = new StringBuffer();
			sb.append(fuiouProperties.getPayType()).append("|").
					append(fuiouProperties.getVersion()).append("|").
					append(fyPayInfo.getMchnt_cd()).append("|").
					append(fyPayInfo.getOrder_id()).append("|").
					append(fyPayInfo.getUser_id()).append("|").
					append(fyPayInfo.getOrder_amt()).append("|").
					append(fyPayInfo.getCard_no()).append("|").
					append(fyPayInfo.getBack_notify_url()).append("|").
					append(fyPayInfo.getCardholder_name()).append("|").
					append(fyPayInfo.getCert_no()).append("|").
					append(fyPayInfo.getCert_type()).append("|").
					append(fuiouProperties.getLogoTp()).append("|").
					append(fyPayInfo.getPage_notify_url()).append("|").
					append(fyPayInfo.getPage_notify_url_err()).append("|").append(fuiouProperties.getMd5Key());

			log.info("app pay 签名前：" + sb.toString());
			String signStr = MD5.MD5Encode(sb.toString());
			log.info("app pay 签名后：" + signStr);

			StringBuffer sbFm = new StringBuffer();
			sbFm.append("<ORDER>");
			sbFm.append("<VERSION>").append(fuiouProperties.getVersion()).append("</VERSION>");
			sbFm.append("<LOGOTP>").append(fuiouProperties.getLogoTp()).append("</LOGOTP>");
			sbFm.append("<MCHNTCD>").append(fyPayInfo.getMchnt_cd()).append("</MCHNTCD>");
			sbFm.append("<TYPE>").append(fuiouProperties.getPayType()).append("</TYPE>");
			sbFm.append("<MCHNTORDERID>").append(fyPayInfo.getOrder_id()).append("</MCHNTORDERID>");
			sbFm.append("<USERID>").append(fyPayInfo.getUser_id()).append("</USERID>");
			sbFm.append("<AMT>").append(fyPayInfo.getOrder_amt()).append("</AMT>");
			sbFm.append("<BANKCARD>").append(fyPayInfo.getCard_no()).append("</BANKCARD>");
			sbFm.append("<BACKURL>").append(fyPayInfo.getBack_notify_url()).append("</BACKURL>");
			sbFm.append("<HOMEURL>").append(fyPayInfo.getPage_notify_url()).append("</HOMEURL>");
			sbFm.append("<REURL>").append(fyPayInfo.getPage_notify_url_err()).append("</REURL>");
			sbFm.append("<NAME>").append(fyPayInfo.getCardholder_name()).append("</NAME>");
			sbFm.append("<IDTYPE>").append(fyPayInfo.getCert_type()).append("</IDTYPE>");
			sbFm.append("<IDNO>").append(fyPayInfo.getCert_no()).append("</IDNO>");
			sbFm.append("<REM1>").append("").append("</REM1>");
			sbFm.append("<REM2>").append("").append("</REM2>");
			sbFm.append("<REM3>").append("").append("</REM3>");
			sbFm.append("<SIGNTP>").append("md5").append("</SIGNTP>");
			sbFm.append("<SIGN>").append(signStr).append("</SIGN>");
			sbFm.append("</ORDER>");
			log.info("app pay fm:" + sbFm.toString());
			String xmlFm = DESCoderFUIOU.desEncrypt(sbFm.toString(), DESCoderFUIOU.getKeyLength8(fuiouProperties.getMd5Key()));
			log.info("app pay xml 签名结果：" + xmlFm);

			Map<String, Object> userInfoMap = new HashMap<String, Object>();
			userInfoMap.put("req_url", fuiouProperties.getPayUrl());
			userInfoMap.put("ENCTP", fuiouProperties.getEnctp());
			userInfoMap.put("VERSION", fuiouProperties.getVersion());
			userInfoMap.put("MCHNTCD", fyPayInfo.getMchnt_cd());
			userInfoMap.put("FM", xmlFm.replace("+","%2B"));
			resMap.put("orderInfo", userInfoMap);
			//查询用户账户信息
			SiteUserAccount siteUserAccount = new SiteUserAccount();
			SiteUserAccountExample example = new SiteUserAccountExample();
			example.createCriteria().andUserIdEqualTo(siteUserBuy.getUserId());
			List<SiteUserAccount> userAccountList = siteUserAccountMapper.selectByExample(example);
			if (userAccountList == null || userAccountList.size() == 0) {//无用户账户记录
				resMap.put("result_code", MapUtil.INTF_ERR_CODE);
				resMap.put("result_info", "无用户账户信息");
				return resMap;
			}

			//插入充值记录信息 设置状态为充值中
			SiteUserRecharge siteUserRecharge = getSiteUserRecharge(siteUserBuy, siteUser, siteUserAccount);
			if (siteUserRecharge == null) {
				resMap.put("result_code", MapUtil.INTF_ERR_CODE);
				resMap.put("result_info", "用户信息不全");
				return resMap;
			}
			siteUserRechargeMapper.insertSelective(siteUserRecharge);
		} catch (Exception e) {
			log.info("充值失败");
		}
		return resMap;
	}

	@Override
	public Map<String, Object> rechargeNotify(FyPayReturnInfo fyPayReturnInfo) throws RuntimeException{
		Map<String, Object> resMap = new HashMap<String, Object>();
		//try {
			if (fyPayReturnInfo.getOrder_amt() == null) {
				resMap.put("result_code", MapUtil.INTF_ERR_CODE);
				resMap.put("result_info", "充值金额为空");
				return resMap;
			}
			if ("0".compareTo(fyPayReturnInfo.getOrder_amt()) != -1) {//充值金额大于0
				resMap.put("result_code", MapUtil.INTF_ERR_CODE);
				resMap.put("result_info", "充值金额有误");
				return resMap;
			}
			//获取充值记录
			SiteUserRechargeExample1 example = new SiteUserRechargeExample1();
			String orderNo = fyPayReturnInfo.getOrder_id();
			BigDecimal amount = new BigDecimal(fyPayReturnInfo.getOrder_amt());
			example.createCriteria().andOrderIdEqualTo(orderNo).andAmountEqualTo(amount).andStatusEqualTo(1);
			List<SiteUserRecharge> siteUserRechargeList = siteUserRechargeMapper.selectByExample(example);
			if (siteUserRechargeList == null || siteUserRechargeList.size() == 0) {
				log.info("充值通知：未查到处理中的充值记录，订单号：" + orderNo + "充值金额：" + amount);
				resMap.put("result_code", MapUtil.INTF_ERR_CODE);
				resMap.put("result_info", "未查到处理中的充值记录，订单号：" + orderNo + "充值金额：" + amount);
				return resMap;
			}
			//处理业务
			log.info("进入dealRecharge");
			dealRecharge(fyPayReturnInfo);
		/*} catch (Exception e) {
			log.info("充值失败" + e);
			resMap.put("result_code", MapUtil.INTF_ERR_CODE);
			resMap.put("result_info", "请求失败");
		}*/
		return resMap;
	}

	@Override
	public void rechargeQuery(SiteUserRecharge siteUserRecharge) throws RuntimeException{
		if (siteUserRecharge != null) {
			Map<String, String> request = new HashMap<String, String>();
			// RSA加签字符串
			StringBuffer sb = new StringBuffer();
			sb.append("1.0").append("|").
					append(fuiouProperties.getMerchId()).append("|").
					append(siteUserRecharge.getOrderId()).append("|").
					append(fuiouProperties.getMd5Key());

			log.info("app pay 签名前：" + sb.toString());
			String signStr = MD5.MD5Encode(sb.toString());
			log.info("app pay 签名后：" + signStr);

			StringBuffer sbFm = new StringBuffer();
			sbFm.append("<ORDER>");
			sbFm.append("<VERSION>").append("1.0").append("</VERSION>");
			sbFm.append("<MCHNTCD>").append(fuiouProperties.getMerchId()).append("</MCHNTCD>");
			sbFm.append("<MCHNTORDERID>").append(siteUserRecharge.getOrderId()).append("</MCHNTORDERID>");
			sbFm.append("<REM1>").append("").append("</REM1>");
			sbFm.append("<REM2>").append("").append("</REM2>");
			sbFm.append("<REM3>").append("").append("</REM3>");
			sbFm.append("<SIGN>").append(signStr).append("</SIGN>");
			sbFm.append("</ORDER>");
			log.info("app pay fm:" + sbFm.toString());
			String res = "";
			request.put("FM", sbFm.toString());
			HttpPoster httpPoster = new HttpPoster();
			try {
				res = httpPoster.post(fuiouProperties.getQueryUrl(), request);
				log.info("查询返回结果：" + res);
			} catch (Exception e) {
				log.info("查询失败：" + e);
				return;
			}
			//业务处理
			if (res == null || "".equals(res)) {
				log.info("三方返回数据为空");
				return;
			}
			String version = res.substring(res.indexOf("<VERSION>")+9, res.indexOf("</VERSION>"));
			String code = res.substring(res.indexOf("<RESPONSECODE>")+14, res.indexOf("</RESPONSECODE>"));
			String message = res.substring(res.indexOf("<RESPONSEMSG>")+13, res.indexOf("</RESPONSEMSG>"));
			String orderId = res.substring(res.indexOf("<MCHNTORDERID>")+14, res.indexOf("</MCHNTORDERID>"));
			String signed = res.substring(res.indexOf("<SIGN>")+6, res.indexOf("</SIGN>"));
			StringBuffer signStred = new StringBuffer();
			signStred.append(version).append("|");
			signStred.append(code).append("|");
			signStred.append(message).append("|");
			signStred.append(orderId).append("|");
			signStred.append(fuiouProperties.getMd5Key());

			String sign = MD5.MD5Encode(signStred.toString());
			if (!sign.equals(signed)) {
				log.info("充值 富友支付查询验签失败");
				return;
			}
			FyPayReturnInfo fyPayReturnInfo = new FyPayReturnInfo();
			fyPayReturnInfo.setOrder_amt(siteUserRecharge.getAmount().toString());
			fyPayReturnInfo.setOrder_id(orderId);
			fyPayReturnInfo.setOrder_pay_code(code);
			fyPayReturnInfo.setOrder_pay_msg(message);

			dealRecharge(fyPayReturnInfo);
		}
	}

	private SiteUserRecharge getSiteUserRecharge(SiteUserBuy siteUserBuy, SiteUser siteUser, SiteUserAccount siteUserAccount) {
//		SiteUserRecharge siteUserRecharge = new SiteUserRecharge();
//		siteUserRecharge.setOrderId(siteUserBuy.getOrderNo());
//		siteUserRecharge.setUserId(siteUserBuy.getUserId());
//		siteUserRecharge.setAmount(siteUserBuy.getAmount());
//		siteUserRecharge.setInitialAmount(siteUserAccount.getTotalRecharge());
//		if (siteUserAccount.getTotalRecharge() == null) {
//			siteUserAccount.setTotalRecharge(new BigDecimal(0));
//		}
//		siteUserRecharge.setFinalAmount(siteUserBuy.getAmount().add(siteUserAccount.getTotalRecharge()));
//		siteUserRecharge.setProductId(siteUserBuy.getProductId());
//		siteUserRecharge.setInfo("用户：" + siteUserBuy.getUserId() + " 购买产品：" + siteUserBuy.getProductId() + " 金额：" + siteUserBuy.getAmount() + " 元");
//		siteUserRecharge.setStatus(1);
//		siteUserRecharge.setCreateTime(new Date());
//		siteUserRecharge.setType(1);
//		siteUserRecharge.setBankCard(siteUser.getBankCardNo());
//		return siteUserRecharge;
		
		return null;
	}

	//处理业务
	@Transactional
	public String dealRecharge(FyPayReturnInfo fyPayReturnInfo){
		//try {
			log.info("业务处理开始----");
			String orderNo = fyPayReturnInfo.getOrder_id();//订单号
			String message = fyPayReturnInfo.getOrder_pay_msg();//三方返回信息
			String code = fyPayReturnInfo.getOrder_pay_code();//三方返回码
			BigDecimal amount = new BigDecimal(fyPayReturnInfo.getOrder_amt());//交易金额

			//1.获取充值记录
			SiteUserRechargeExample1 example = new SiteUserRechargeExample1();
			example.createCriteria().andOrderIdEqualTo(orderNo).andAmountEqualTo(amount).andStatusEqualTo(1);
			List<SiteUserRecharge> siteUserRechargeList = siteUserRechargeMapper.selectByExample(example);
			if (siteUserRechargeList == null || siteUserRechargeList.size() == 0) {
				log.info("未查到处理中的充值记录，订单号：" + orderNo + "充值金额：" + amount);
				return null;
			}
			//2.判断是否处理充值记录 初期余额=用户账户表中累计充值金额
			SiteUserRecharge siteUserRecharge = siteUserRechargeList.get(0);
			//查询用户账户信息
			SiteUserAccountExample userAccountExample = new SiteUserAccountExample();
			userAccountExample.createCriteria().andUserIdEqualTo(siteUserRecharge.getUserId());
			List<SiteUserAccount> userAccountList = siteUserAccountMapper.selectByExample(userAccountExample);
			if (userAccountList == null || userAccountList.size() == 0) {//无用户账户记录
				log.info("未查到用户账户记录，userId：" + siteUserRecharge.getUserId());
				return null;
			}

			SiteUserAccount siteUserAccount = userAccountList.get(0);
//			BigDecimal initialAmount = siteUserRecharge.getInitialAmount();//期初金额
			BigDecimal initialAmount = null;//期初金额
			BigDecimal totalRecharge = siteUserAccount.getTotalRecharge();//充值累计金额
			//if (initialAmount.equals(totalRecharge)) {
				//3.更新充值记录状态
				siteUserRecharge.setStatus(3);
				if ("0000".equals(code)) {
					siteUserRecharge.setStatus(2);
				}

				siteUserRecharge.setCallbackMsg(fyPayReturnInfo.toString());
				siteUserRecharge.setRetMsg(message);
				siteUserRecharge.setRetMsgConf(message);//zxl
				siteUserRecharge.setRetCode(code);
				siteUserRecharge.setTradeNo(fyPayReturnInfo.getFy_ssn());
				siteUserRecharge.setReplyTime(new Date());//更新时间
				SiteUserRechargeExample1 rechargeExample = new SiteUserRechargeExample1();
				rechargeExample.createCriteria().andIdEqualTo(siteUserRecharge.getId()).andOrderIdEqualTo(orderNo)
						.andInitialAmountEqualTo(initialAmount).andAmountEqualTo(amount).andStatusEqualTo(1);

				log.info("更新siteUserRecharge，订单："+siteUserRecharge.getOrderId()+"金额："+siteUserRecharge.getAmount());
				siteUserRechargeMapper.updateByExampleSelective(siteUserRecharge, rechargeExample);

				// 4.判断是否充值成功 成功更新用户账户表 和系统账户表、日志状态
				if (2 == siteUserRecharge.getStatus()) {
					log.info("支付成功处理业务开始");
//					siteUserAccount.setTotalRecharge(siteUserRecharge.getAmount().add(totalRecharge));
					//siteUserAccount.setTotalAsset(siteUserRecharge.getAmount().add(siteUserAccount.getTotalAsset()));
					SiteUserAccountExample accountExample = new SiteUserAccountExample();
					accountExample.createCriteria().andUserIdEqualTo(siteUserRecharge.getUserId()).andTotalRechargeEqualTo(totalRecharge);
					log.info("更新siteUserAccount，订单："+siteUserRecharge.getOrderId()+"金额："+siteUserRecharge.getAmount());
					siteUserAccountMapper.updateByExampleSelective(siteUserAccount, accountExample);

					String outMsg ="";
					//查询用户信息
					SiteUser siteUser = new SiteUser();
					SiteUserExample siteUserExample = new SiteUserExample();
					siteUserExample.createCriteria().andUserIdEqualTo(siteUserRecharge.getUserId());
					List<SiteUser> siteUserList = siteUserMapper.selectByExample(siteUserExample);
					if (siteUserList != null && siteUserList.size() > 0) {
						siteUser = siteUserList.get(0);
						outMsg = siteUserRecharge.getUserId()+siteUser.getBankCardNo();
					}

					String inMsg ="";
							SiteUserBuyExample siteUserBuyExample = new SiteUserBuyExample();
					siteUserBuyExample.createCriteria().andOrderNoEqualTo(orderNo);
					List<SiteUserBuy> siteUserBuys = siteUserBuyMapper.selectByExample(siteUserBuyExample);
					if (siteUserBuys!= null){
						SiteUserBuy siteUserBuy = siteUserBuys.get(0);
						Integer type = siteUserBuy.getProductType();
						if (1 == type){//1:活期，2:定期
							inMsg = "活期";
							siteSysAccountService.updateBanlanceByUserId(Constants.SYS_ACCOUNT_10002, amount.negate(), BigDecimal.ZERO, Constants.ACCOUNT_LOG_TYPE_1,
									siteUserRecharge.getUserId(), Constants.SYS_ACCOUNT_10002,
									orderNo, "", "", "", inMsg, outMsg);
						}
						if (2 == type){
							inMsg = "定期";
							siteSysAccountService.updateBanlanceByUserId(Constants.SYS_ACCOUNT_10003, amount.negate(), BigDecimal.ZERO, Constants.ACCOUNT_LOG_TYPE_1,
									siteUserRecharge.getUserId(), Constants.SYS_ACCOUNT_10003,
									orderNo, "", "","", inMsg, outMsg);
						}
					}
					log.info("更新系统账户，订单："+siteUserRecharge.getOrderId()+"金额："+siteUserRecharge.getAmount());
					//系统账户相关
					//总账户
					siteSysAccountService.updateBanlanceByUserId(Constants.SYS_ACCOUNT_10000, amount.negate(), BigDecimal.ZERO, Constants.ACCOUNT_LOG_TYPE_1,
							siteUserRecharge.getUserId(), Constants.SYS_ACCOUNT_10000,
							orderNo, "", "", "", inMsg, outMsg);
					//手续费账户
					siteSysAccountService.updateBanlanceByUserId(Constants.SYS_ACCOUNT_10004, amount.multiply(new BigDecimal(fuiouProperties.getRate())), BigDecimal.ZERO, Constants.ACCOUNT_LOG_TYPE_1,
							siteUserRecharge.getUserId(), Constants.SYS_ACCOUNT_10004,
							orderNo, "", "", "", inMsg, outMsg);

				}
				log.info("更新siteUserBuy，订单："+siteUserRecharge.getOrderId());
				siteUserBuyService.rechargeNotify(siteUserRecharge);
			/*} else {
				log.info("金额不匹配---充值期初金额：" + initialAmount + "累计充值金额：" + totalRecharge);
				return null;
			}*/
		/*} catch (Exception e) {
			log.info("处理业务逻辑失败"+e);
			return null;
		}*/
		return "OK";
	}
}
